<?php
namespace app\model;

/**
 * Author: cbw
 * Desc: 阿里短信类
 * Time: 2022/12/5 09:36
 * Email: 17854288794@163.com
 */

require_once PATH_MODULE .'define.php';
class AliSms{

    private function encode($str)
    {
        $res = urlencode($str);
        $res = preg_replace("/\+/", "%20", $res);
        $res = preg_replace("/\*/", "%2A", $res);
        $res = preg_replace("/%7E/", "~", $res);
        return $res;
    }

    private function fetchContent($url, $method, $body) {
        $ch = curl_init();
        if($method == 'POST') {
            curl_setopt($ch, CURLOPT_POST, 1);//post提交方式
            curl_setopt($ch, CURLOPT_POSTFIELDS, $body);
        } else {
            $url .= '?'.$body;
        }
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_TIMEOUT, 5);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($ch, CURLOPT_HTTPHEADER, array(
            "x-sdk-client" => "php/2.0.0"
        ));
        if(substr($url, 0,5) == 'https') {
            curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
            curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
        }
        $rtn = curl_exec($ch);
        if($rtn === false) {
            // 大多由设置等原因引起，一般无法保障后续逻辑正常执行，
            // 所以这里触发的是E_USER_ERROR，会终止脚本执行，无法被try...catch捕获，需要用户排查环境、网络等故障
            trigger_error("[CURL_" . curl_errno($ch) . "]: " . curl_error($ch), E_USER_ERROR);
        }
        curl_close($ch);
        return $rtn;
    }

    public function request($accessKeyId, $accessKeySecret, $params, $security=false, $method='POST') {
        $domain = 'dysmsapi.aliyuncs.com';
        $apiParams = array_merge(array (
            "SignatureMethod" => "HMAC-SHA1",
            "SignatureNonce" => uniqid(mt_rand(0,0xffff), true),
            "SignatureVersion" => "1.0",
            "AccessKeyId" => $accessKeyId,
            "Timestamp" => gmdate("Y-m-d\TH:i:s\Z"),
            "Format" => "JSON",
        ), $params);
        ksort($apiParams);
        $sortedQueryStringTmp = "";
        foreach ($apiParams as $key => $value) {
            $sortedQueryStringTmp .= "&" . $this->encode($key) . "=" . $this->encode($value);
        }
        $stringToSign = "${method}&%2F&" . $this->encode(substr($sortedQueryStringTmp, 1));
        $sign = base64_encode(hash_hmac("sha1", $stringToSign, $accessKeySecret . "&",true));
        $signature = $this->encode($sign);
        $url = ($security ? 'https' : 'http')."://{$domain}/";
        try {
            $content = $this->fetchContent($url, $method, "Signature={$signature}{$sortedQueryStringTmp}");
            $res  = json_decode($content,true);
            if ($res['Code']!='OK'){
                $error = $this->getErrorMessage ($res['Code']);
                yxlog('阿里短信接口数据获取失败:'.$error);
            }
            return $res;
        } catch( \Exception $e) {
            return false;
        }
    }

    /**
     * Desc:单次发送短息 验证码使用以及模板消息
     * User:cbw
     * Email:17854288794@163.com
     * Time: 2022/12/5 16:15
     * @param $mobile
     * @param $template_param
     * @param $config
     * @return false|mixed
     */
    public function sendSms($mobile,$template_param,$config)
    {
        try {
            // *** 需用户填写部分 ***
            // fixme 必填：是否启用https
            $security = false;
            // fixme 必填: 请参阅 https://ak-console.aliyun.com/ 取得您的AK信息
            $accessKeyId = $config['accessKeyId'];
            $accessKeySecret = $config['accessKeySecret'];
            // fixme 必填: 短信接收号码
            $params["PhoneNumbers"] = $mobile;
            // fixme 必填: 短信签名，应严格按"签名名称"填写，请参考: https://dysms.console.aliyun.com/dysms.htm#/develop/sign
            $params["SignName"] = $config['signName'];
            // fixme 必填: 短信模板Code，应严格按"模板CODE"填写, 请参考: https://dysms.console.aliyun.com/dysms.htm#/develop/template
            $params["TemplateCode"] = $config['templateCode'];
            // fixme 可选: 设置模板参数, 假如模板中存在变量需要替换则为必填项
            $params['TemplateParam'] = $template_param;
            // fixme 可选: 设置发送短信流水号
//            $params['OutId'] = "12345";


            // *** 需用户填写部分结束, 以下代码若无必要无需更改 ***
            if(!empty($params["TemplateParam"]) && is_array($params["TemplateParam"])) {
                $params["TemplateParam"] = json_encode($params["TemplateParam"], JSON_UNESCAPED_UNICODE);
            }
            $params['RegionId'] = 'cn-hangzhou';
            $params['Action'] = 'SendSms';
            $params['Version'] = '2017-05-25';
            $content = $this->request($accessKeyId,$accessKeySecret,$params,$security);
            if ($content['Code']=='OK'){
                //todo  执行记录入库
            }
            return $content;
        }catch (Exception $e){
            yxlog('短信发送异常:'.$e->getMessage());
        }
    }

    /**
     * Desc:批量发送短信 模板消息  存在一定延时概率
     * User:cbw
     * Email:17854288794@163.com
     * Time: 2022/12/5 16:15
     * @param $mobileArr array
     * @param $template_params_arr array
     * @param $config
     * @return false|mixed
     */
    public function sendBatchSms($mobileArr,$template_params_arr,$config)
    {
        try{
            // *** 需用户填写部分 ***
            // fixme 必填：是否启用https
            $security = false;
            // fixme 必填: 请参阅 https://ak-console.aliyun.com/ 取得您的AK信息
            $accessKeyId = $config['accessKeyId'];
            $accessKeySecret = $config['accessKeySecret'];
            // fixme 必填: 待发送手机号。支持JSON格式的批量调用，批量上限为100个手机号码,批量调用相对于单条调用及时性稍有延迟,验证码类型的短信推荐使用单条调用的方式
            $params["PhoneNumberJson"] = $mobileArr;
            // fixme 必填: 短信签名，支持不同的号码发送不同的短信签名，每个签名都应严格按"签名名称"填写，请参考: https://dysms.console.aliyun.com/dysms.htm#/develop/sign
            $params["SignNameJson"] = $config['signName'];
            // fixme 必填: 短信模板Code，应严格按"模板CODE"填写, 请参考: https://dysms.console.aliyun.com/dysms.htm#/develop/template
            $params["TemplateCode"] = $config['templateCode'];
            // fixme 必填: 模板中的变量替换JSON串,如模板内容为"亲爱的${name},您的验证码为${code}"时,此处的值为
            // 友情提示:如果JSON中需要带换行符,请参照标准的JSON协议对换行符的要求,比如短信内容中包含\r\n的情况在JSON中需要表示成\\r\\n,否则会导致JSON在服务端解析失败
            $params["TemplateParamJson"] =$template_params_arr;
            // *** 需用户填写部分结束, 以下代码若无必要无需更改 ***
            $params["TemplateParamJson"]  = json_encode($params["TemplateParamJson"], JSON_UNESCAPED_UNICODE);
            $params["SignNameJson"] = json_encode($params["SignNameJson"], JSON_UNESCAPED_UNICODE);
            $params["PhoneNumberJson"] = json_encode($params["PhoneNumberJson"], JSON_UNESCAPED_UNICODE);

            if(!empty($params["SmsUpExtendCodeJson"]) && is_array($params["SmsUpExtendCodeJson"])) {
                $params["SmsUpExtendCodeJson"] = json_encode($params["SmsUpExtendCodeJson"], JSON_UNESCAPED_UNICODE);
            }
            $params['RegionId'] = 'cn-hangzhou';
            $params['Action'] = 'SendBatchSms';
            $params['Version'] = '2017-05-25';
            // 此处可能会抛出异常，注意catch
            $content = $this->request($accessKeyId, $accessKeySecret, $params, $security);
            if ($content['Code']=='OK'){
                //todo  执行记录入库
            }
            return $content;
        }catch (Exception $e){
            yxlog('短信批量发送异常:'.$e->getMessage());
        }
    }

    public function querySmsTemplateList($page=1,$size=50,$config)
    {
        try {
            // *** 需用户填写部分 ***
            // fixme 必填：是否启用https
            $security = false;
            // fixme 必填: 请参阅 https://ak-console.aliyun.com/ 取得您的AK信息
            $accessKeyId = $config['accessKeyId'];
            $accessKeySecret = $config['accessKeySecret'];
            // fixme 必填: 展示第几页的模板信息。默认取值为1。
            $params["PageIndex"] = $page;
            // fixme 必填: 每页展示的模板个数。取值范围：1~50。
            $params["PageSize"] = $size;

            // *** 需用户填写部分结束, 以下代码若无必要无需更改 ***
            $params['RegionId'] = 'cn-hangzhou';
            $params['Action'] = 'QuerySmsTemplateList';
            $params['Version'] = '2017-05-25';
            $content = $this->request($accessKeyId,$accessKeySecret,$params,$security);
            return $content;
        }catch (Exception $e){
            yxlog('短信模板查询异常:'.$e->getMessage());
        }
    }

    /**
     * Desc:获取错误信息
     * User:cbw
     * Email:17854288794@163.com
     * Time: 2022/12/5 10:42
     * @param $status
     * @return string
     */
    public function getErrorMessage($status)
    {
        $message = array (
            'isv.BUSINESS_LIMIT_CONTROL' => '短信发送频率超限',
            'isv.DAY_LIMIT_CONTROL' => '已经达到您在控制台设置的短信日发送量限额值',
            'isv.SMS_CONTENT_ILLEGAL' => '短信内容包含禁止发送内容,请修改短信文案',
            'isv.SMS_SIGN_ILLEGAL' => '签名禁止使用,请在短信服务控制台中申请符合规定的签名',
            'isp.RAM_PERMISSION_DENY' => 'RAM权限不足。,请为当前使用的AK对应子账号进行授权：AliyunDysmsFullAccess（管理权限）',
            'isv.OUT_OF_SERVICE' => '余额不足。余额不足时，套餐包中即使有短信额度也无法发送短信',
            'isv.PRODUCT_UN_SUBSCRIPT' => '未开通云通信产品的阿里云客户',
            'isv.PRODUCT_UNSUBSCRIBE' => '产品未开通',
            'isv.ACCOUNT_NOT_EXISTS' => '账户不存在，使用了错误的账户名称或AK',
            'isv.ACCOUNT_ABNORMAL' => '账户异常',
            'isv.SMS_TEMPLATE_ILLEGAL' => '短信模板不存在，或未经审核通过',
            'isv.SMS_SIGNATURE_ILLEGAL' => '签名不存在，或未经审核通过',
            'isv.INVALID_PARAMETERS' => '参数格式不正确',
            'isv.MOBILE_NUMBER_ILLEGAL' => '机号码格式错误',
            'isv.MOBILE_COUNT_OVER_LIMIT' => '参数PhoneNumbers中指定的手机号码数量超出限制',
            'isv.TEMPLATE_MISSING_PARAMETERS' => '模版缺少变量',
            'isv.BLACK_KEY_CONTROL_LIMIT' => '黑名单管控',
            'isv.PARAM_LENGTH_LIMIT' => '参数超出长度限制',
            'isv.PARAM_NOT_SUPPORT_URL' => '不支持URL',
            'isv.AMOUNT_NOT_ENOUGH' => '账户余额不足',
            'SignatureDoesNotMatch' => '签名（Signature）加密错误',
        );
        if (isset ( $message [$status] )) {
            return $message [$status];
        }
        return $status;
    }

    public function addSmsFlagItem($data)
    {

        $res = $insertid = db_insert(t_sms_send_flag,$data);
    }

}